﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;

namespace TiposComuns.Objectos
{

    /// <summary>
    /// This class represents a view of the state of the three servers.
    /// Each server in the list view is considered to be alive and the order
    /// indicates that the first is the primary and the others the backups.
    /// </summary>
    [Serializable]
    public class View
    {
        #region Constructors
        public View()
        {
            this.VID = 0;
            this.ViewState = new List<int>(3);
        }

        public View(int vid, List<int> view)
        {
            this.VID = vid;
            this.ViewState = view;
        }
        #endregion

        #region Modifiers
        /// <summary>
        /// Identifier of the view, that is incremented on each global state change
        /// </summary>
        public int VID
        {
            [MethodImpl(MethodImplOptions.Synchronized)]
            get;

            [MethodImpl(MethodImplOptions.Synchronized)]
            set; 
        }

        /// <summary>
        /// List of server identifiers. The order is important, so that it indicates 
        /// how should the primary server be choosed.
        /// </summary>
        public List<int> ViewState
        {
            [MethodImpl(MethodImplOptions.Synchronized)]
            get;

            [MethodImpl(MethodImplOptions.Synchronized)]
            set; 
        }
        #endregion

        #region Methods
        public View Clone()
        {
            List<int> list = new List<int>();
            list.AddRange(this.ViewState);
            return new View(this.VID, list);
        }

        /// <summary>
        /// Increments the VID
        /// </summary>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void Inc()
        {
            this.VID++;
        }

        /// <summary>
        /// Decreases the VID
        /// </summary>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void Dec()
        {
            this.VID--;
        }

        /// <summary>
        /// Removes a server from the list of active servers
        /// </summary>
        /// <param name="serv">Server number(1,2 or 3)</param>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void RemoveServer(int serv)
        {
            this.ViewState.Remove(serv);
        }

        /// <summary>
        /// Adds a server to the end of the list of active server.
        /// The added server may not become the primary.
        /// </summary>
        /// <param name="serv">Server number</param>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void AddServer(int serv)
        {
            if(!ViewState.Contains(serv))
            {
                this.ViewState.Add(serv);
            }
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        public void AddPrimaryServer(int serv)
        {
            if (this.ViewState.Contains(serv))
            {
                int iserv = this.ViewState.IndexOf(serv);
                int aprim = this.ViewState[0];
                this.ViewState[0] = serv;
                this.ViewState[iserv] = aprim;
            }
            else if (this.ViewState.Count > 0)
            {
                int aprim = this.ViewState[0];
                this.ViewState[0] = serv;
                this.ViewState.Add(aprim);
            }
            else
            {
                this.ViewState.Add(serv);
            }
        }
        #endregion 
    }
}